package com.alorm.core.sqlite.sqlgen;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Queue;

import android.content.Context;
import android.util.Log;

import com.alorm.core.exceptions.AlormException;
import com.alorm.utils.AlormUtils;

public class SqlStatementsGenerator {

	private boolean cascade = false;
	private List<Class> listClassPer;

	public SqlStatementsGenerator(Context context) {
		listClassPer = AlormUtils.getListClassPer(context);

	}

	public String getSaveStatement(Object obj) throws AlormException {
		String req = null;
		try {

			Class objClass = obj.getClass();
			if (!listClassPer.contains(objClass))
				throw new AlormException("l'objet a inserer et non valide !!");

			String objClassName = AlormUtils.getClassName(objClass);
			Field fields[] = objClass.getDeclaredFields();
			String reqPart1 = "";
			String reqPart2 = "";
			Method method;
			Object val;
			for (int i = 1; i < fields.length; i++) {
				Class fieldClass = fields[i].getType();
				if (!fieldClass.equals(ArrayList.class)) {
					reqPart1 = reqPart1 + " " + fields[i].getName() + ",";
					String getterM = AlormUtils.getGetterMethod(fields[i]
							.getName());

					method = objClass.getMethod(getterM);
					val = method.invoke(obj);
					if (!listClassPer.contains(fieldClass)) {
						if (val.getClass().equals(String.class))
							val = "'" + val + "'";

					} else {

						String pkName = AlormUtils.getPkName(fieldClass);
						getterM = AlormUtils.getGetterMethod(pkName);
						method = fieldClass.getMethod(getterM);
						val = method.invoke(val);

					}
					reqPart2 = reqPart2 + " " + val + ",";
				}

			}
			reqPart1 = reqPart1.substring(0, reqPart1.length() - 1);
			reqPart2 = reqPart2.substring(0, reqPart2.length() - 1);
			req = "INSERT INTO " + objClassName + "(" + reqPart1 + ")"
					+ " VALUES (" + reqPart2 + ")";

		} catch (Exception e) {
			throw new AlormException(e);
		}

		return req;
	}

	public List<DeleteStatement> getDeleteStatements(Object pObject) {

		// if (!cascade) {
		// Class lClass = pObject.getClass();
		// Method method = null;
		// String tableName = AlormUtils.getClassName(lClass);
		// String pkName = AlormUtils.getPkName(lClass);
		// String getterMethod = AlormUtils.getGetterMethod(pkName);
		// Number number = null;
		// try {
		//
		// method = lClass.getMethod(getterMethod);
		// number = (Number) method.invoke(pObject);
		//
		// } catch (Exception e) {
		// throw new AlormException("an error has occured due to : ", e);
		// }
		//
		// return new DeleteStatement(tableName, pkName + "= ?",
		// new String[] { String.valueOf(number) });
		//
		// } else {
		//
		// }
		return null;

	}

	public DeleteStatement getDeleteStatement(Object pObject) {

		if (!cascade) {
			Class lClass = pObject.getClass();
			Method method = null;
			String tableName = AlormUtils.getClassName(lClass);
			String pkName = AlormUtils.getPkName(lClass);
			String getterMethod = AlormUtils.getGetterMethod(pkName);

			Number number = null;
			try {

				method = lClass.getMethod(getterMethod);
				
				number = (Number) method.invoke(pObject);
				

			} catch (Exception e) {
				throw new AlormException("an error has occured due to : ", e);
			}

			return new DeleteStatement(tableName, pkName + "= ?",
					new String[] { String.valueOf(number) });

		} else {

		}
		return null;

	}

	public String getUpdateStatement(Object pObject) {
		StringBuilder strb = new StringBuilder("update ");
		Class lClass = pObject.getClass();
		String[] fieldsName = AlormUtils.getAllFieldsName(lClass);
		Map<String, String> map = null;
		String tableName = AlormUtils.getClassName(lClass);
		Method method = null;
		String pkName = AlormUtils.getPkName(lClass);
		String getterMethod = AlormUtils.getGetterMethod(pkName);
		Number number = null;
		try {
			map = AlormUtils.getAllFieldsValue(pObject);
			method = lClass.getMethod(getterMethod);
			number = (Number) method.invoke(pObject);
		} catch (Exception e) {

			throw new AlormException("An error occured :", e);
		}

		strb.append(tableName);
		strb.append(" SET ");

		for (Map.Entry<String, String> entry : map.entrySet()) {

			strb.append(entry.getKey() + "=" + entry.getValue() + "  , ");

		}

		strb.deleteCharAt(strb.length() - 2);
		strb.append(" where ");
		strb.append(pkName);
		strb.append("=");
		strb.append(String.valueOf(number));
		return strb.toString();
	}

	//
	// public static void main(String[] args) {
	//
	// SqlStatementsGenerator sql = new SqlStatementsGenerator();
	// Etudiant e = new Etudiant(1, "taz", "baz");
	// Etudiant e2 = new Etudiant(1, "ez", "eo");
	//
	// System.out.println(sql.getUpdateStatement(e));
	//
	// }

	public boolean isCascade() {
		return cascade;
	}

	public void setCascade(boolean cascade) {
		this.cascade = cascade;
	}

}
